package Test;

import static org.junit.Assert.*;

import java.io.File;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.junit.Test;

import Model.Conference;
import Model.Conference.Role;
import Model.Paper;
import Model.User;

/**
 * Unit tests methods in Conference class. 
 * 
 * @author InnoIrving Estrera
 * */
public class TestConference
{
  private static final User PAUL = new User("Paul Shultz", "PaulS",
      "P@fake.com");
  private static final User WILLIAM = new User("William Kim", "WilliamK",
      "W@fake.com");
  private static final User IRVING = new User("Irving Estrera", "IrvingE",
      "I@fake.com");
  private static final User NATHAN = new User("Nathan Judkins", "NathanJ",
      "N@fake.com");
  private static final User ERIC = new User("Eric Cartman", "EricC",
      "E@fake.com");
  private static final String CONFERENCE_NAME = "Smart Software Development";
  private static final File TEST_FILE = new File("users.txt");
  private static final File TEST_FILE2 = new File("users.txt");
  private static final Date TEST_DEADLINE = new Date(200, 0, 1);

  @Test
  public void test2argConstructor()
  {
    // tests conference with no users
    Conference test_conference = new Conference(CONFERENCE_NAME, PAUL,
        TEST_DEADLINE);
    final String expected_realname = "Paul Shultz";
    final String expected_username = "PaulS";
    final String expected_email = "P@fake.com";
    final User expected_chair = new User("Paul Shultz", "PaulS", "P@fake.com");

    test_conference.addUser(PAUL);
    int expected_size = 1; // just the program chair

    // compares initialized fields of the conference
    assertEquals("compare PC's real name", expected_realname, test_conference
        .programChair().realName());
    assertEquals("compare PC's username", expected_username, test_conference
        .programChair().userName());
    assertEquals("compare emails", expected_email, test_conference
        .programChair().email());
    assertEquals("compare program chairs", expected_chair,
        test_conference.programChair());
    assertEquals("list of users", expected_size, test_conference.users().size());
  }

  @Test
  public void test3ArgConstructor()
  {
    // create predetermined users
    List<User> pre_determined_users = new ArrayList<User>();
    pre_determined_users.add(WILLIAM);
    pre_determined_users.add(ERIC);
    pre_determined_users.add(PAUL);

    // create conference with predetermined users
    Conference test_conference = new Conference(CONFERENCE_NAME, PAUL,
        pre_determined_users, TEST_DEADLINE);

    // conference now should have the list of users, William, Eric and Paul

    // create expected output
    List<User> expected = new ArrayList<User>();
    expected.add(WILLIAM);
    expected.add(ERIC);
    expected.add(PAUL);

    // assertEquals(expected, test_conference.getUsers());
    // assertArrayEquals("3argConstructor", expected.toArray(),
    // test_conference.getUsers().toArray());
    assertTrue(test_conference.users().contains(WILLIAM));
    assertTrue(test_conference.users().contains(ERIC));
    assertTrue(test_conference.users().contains(PAUL));
  }

  @Test
  public void test4ArgConstructor()
  {
    // create expected sub program chair roles
    List<Role> sub_chair_roles = new ArrayList<Role>();
    sub_chair_roles.add(Role.REVIEWER);
    sub_chair_roles.add(Role.SUB_CHAIR);

    // create expected author roles
    List<Role> author_roles = new ArrayList<Role>();
    author_roles.add(Role.AUTHOR);

    // create predetermined users
    List<User> pre_determined_users = new ArrayList<User>();
    pre_determined_users.add(WILLIAM);
    pre_determined_users.add(IRVING);

    // create mappings of User vs. List of Roles, expected output
    Map<User, List<Role>> expected = new HashMap<User, List<Role>>();
    expected.put(WILLIAM, author_roles);
    expected.put(IRVING, sub_chair_roles);
    // create conference with predetermined users and roles
    Conference test_conference = new Conference(CONFERENCE_NAME, PAUL,
        expected, TEST_DEADLINE);

    // test current state based on initialized users/roles
    assertTrue(test_conference.users().size() == 3); //test # of users
    
    //users should contain the following
    assertTrue(test_conference.users().contains(PAUL)); 
    assertTrue(test_conference.users().contains(WILLIAM));
    assertTrue(test_conference.users().contains(IRVING)); 
    assertTrue(test_conference.programChair().equals(PAUL)); //paul is a program chair
    //paul shoul only have 1 role, PC
    assertTrue(test_conference.userMappings().get(PAUL).size() == 1);
    //user mappings for paul should contain enum PROGRAM_CHAIR
    assertTrue(test_conference.userMappings().get(PAUL).contains(Role.PROGRAM_CHAIR));
  }

  @Test
  public void testGetRoles()
  {
    // create a coference
    Conference test_conference = new Conference(CONFERENCE_NAME, PAUL,
        TEST_DEADLINE);
    // add users
    test_conference.addUser(WILLIAM);
    test_conference.addUser(IRVING);
    test_conference.addUser(NATHAN);
    
    test_conference.assignReviewer(IRVING);
    test_conference.assignSubChair(IRVING);
    
    // create william's paper
    Paper william_paper = new Paper("William's Paper", WILLIAM, IRVING, TEST_FILE);

    // check whether william has been assigned any role, should be NONE
    assertTrue(test_conference.userMappings().get(WILLIAM).size() == 0);

    // william submits a paper
    test_conference.addPaper(william_paper);

    // william should now be an author
    assertTrue(test_conference.userMappings().get(WILLIAM).size() == 1);
    assertTrue(test_conference.userMappings().get(WILLIAM)
        .contains(Role.AUTHOR));
  }

  @Test
  public void testUpdateRole() {
    //create expected reviewer roles
    List<Role> reviewer_roles = new ArrayList<Role>();
    reviewer_roles.add(Role.REVIEWER);
    
    // create expected sub program chair roles
    List<Role> sub_chair_roles = new ArrayList<Role>();
    sub_chair_roles.add(Role.REVIEWER);
    sub_chair_roles.add(Role.SUB_CHAIR);

    // create expected author roles
    List<Role> author_roles = new ArrayList<Role>();
    author_roles.add(Role.AUTHOR);

    // create mappings of User vs. List of Roles, expected output
    Map<User, List<Role>> expected = new HashMap<User, List<Role>>();
    expected.put(WILLIAM, author_roles);
    expected.put(IRVING, sub_chair_roles);
    expected.put(NATHAN, reviewer_roles);
    
    //WILLIAM is mapped to author roles
    //IRVING is mapped to subprogram chair roles
    //NATHAN is mapped to reviewer roles
    
    // create conference with predetermined users and roles
    Conference test_conference = new Conference(CONFERENCE_NAME, PAUL,
        expected, TEST_DEADLINE);
    
    //IRVING is a sub program chair
    //WILLIAM is an author
    //PAUL is a Program chair and a subprogram chair
    
    //attempts to assign nathan the role author
    assertFalse(test_conference.updateRole(NATHAN, Role.AUTHOR));
    //should be false since nathan hasnt submitted any papers yet
    
    //attempts to assign William the sub program chair role
    assertFalse(test_conference.updateRole(WILLIAM, Role.SUB_CHAIR));
    //should be false since william is not a reviewer yet
    
    //william can be assigned the reviewer role
    assertTrue(test_conference.updateRole(WILLIAM, Role.REVIEWER));
    //should be true since anyone is allowed to be a reviewer
    
    //attempts to assign william sub program chair again after
    //being assigned the reviewer role
    assertTrue(test_conference.updateRole(WILLIAM, Role.SUB_CHAIR));
    //should be true because William is now a reviewer
  }
  
  @Test
  public void testCheckEligibility() {
    //create expected reviewer roles
    List<Role> reviewer_roles = new ArrayList<Role>();
    reviewer_roles.add(Role.REVIEWER);
    
    // create expected sub program chair roles
    List<Role> sub_chair_roles = new ArrayList<Role>();
    sub_chair_roles.add(Role.REVIEWER);
    sub_chair_roles.add(Role.SUB_CHAIR);

    // create expected author roles
    List<Role> author_roles = new ArrayList<Role>();
    author_roles.add(Role.AUTHOR);

    // create mappings of User vs. List of Roles, expected output
    Map<User, List<Role>> expected = new HashMap<User, List<Role>>();
    expected.put(WILLIAM, author_roles);
    expected.put(IRVING, sub_chair_roles);
    expected.put(NATHAN, reviewer_roles);
    
    // create conference with predetermined users and roles
    Conference test_conference = new Conference(CONFERENCE_NAME, PAUL,
        expected, TEST_DEADLINE);
    
    //IRVING is a sub program chair
    //WILLIAM is an author
    //PAUL is a Program chair and a subprogram chair
    
    //check william's eligibility to be a reviewer
    assertTrue(test_conference.checkEligibility(WILLIAM, Role.REVIEWER));
    //should be true since anyone can become a reviewer
    
    //check william's eligibility to be a sub program chair
    assertFalse(test_conference.checkEligibility(WILLIAM, Role.SUB_CHAIR));
    //should be false since william is not a reviewer yet
    
    //check nathan's eligibility to be a sub program chair
    assertTrue(test_conference.checkEligibility(NATHAN, Role.SUB_CHAIR));
    //should be true since nathan is already a reviewer
    
    //check nathan's eligibility to be an author
    assertFalse(test_conference.checkEligibility(NATHAN, Role.AUTHOR));
    //should be false since nathan hasnt submitted a paper yet
    
    //checks Paul's eligibility to be an author
    assertFalse(test_conference.checkEligibility(PAUL, Role.AUTHOR));
    //should be false since Paul has not submitted any papers
    
    //Paul is already a sub program chair
    assertFalse(test_conference.checkEligibility(PAUL, Role.SUB_CHAIR));
    //you cannot re-assign someone who is already that role
    
    //following tests are the same as the previous one
    //tests for roles that you have already assigned to someone
    assertFalse(test_conference.checkEligibility(IRVING, Role.REVIEWER));
    assertFalse(test_conference.checkEligibility(IRVING, Role.SUB_CHAIR));
    assertFalse(test_conference.checkEligibility(WILLIAM, Role.AUTHOR));
    assertFalse(test_conference.checkEligibility(NATHAN, Role.REVIEWER));
  }

  @Test
  public void testSubprogramChairInitialization()
  {
    // create expected sub program chair roles
    List<Role> sub_chair_roles = new ArrayList<Role>();
    sub_chair_roles.add(Role.REVIEWER);
    sub_chair_roles.add(Role.SUB_CHAIR);

    // create expected author roles
    List<Role> author_roles = new ArrayList<Role>();
    author_roles.add(Role.AUTHOR);

    // create expected reviewer roles
    List<Role> reviewer_roles = new ArrayList<Role>();
    reviewer_roles.add(Role.REVIEWER);

    // create predetermined users
    List<User> pre_determined_users = new ArrayList<User>();
    pre_determined_users.add(WILLIAM);
    pre_determined_users.add(IRVING);
    pre_determined_users.add(NATHAN);

    // create mappings of User vs. List of Roles, expected output
    Map<User, List<Role>> pre_determined_roles = new HashMap<User, List<Role>>();
    pre_determined_roles.put(WILLIAM, author_roles); // william is an author
    pre_determined_roles.put(IRVING, sub_chair_roles); // irving is a sub
                                                       // program chair
    pre_determined_roles.put(NATHAN, reviewer_roles); // nathan is a reviewer

    // create conference with predetermined users and roles
    Conference test_conference = new Conference(CONFERENCE_NAME, PAUL,
        pre_determined_roles, TEST_DEADLINE);

    //the conference should have 4 users
    assertTrue(test_conference.users().size() == 4);
    
    //the conference should have 1 sub program chair
    assertTrue(test_conference.subProgramChairs().size() == 1);
    
    //that program chair is irving
    assertTrue(test_conference.containsSubchair(IRVING));
  }

  @Test
  public void testAddPaper()
  {
    List<User> pre_determined_users = new ArrayList<User>();
    pre_determined_users.add(WILLIAM);
    pre_determined_users.add(ERIC);
    pre_determined_users.add(IRVING);

    // create conference with predetermined users (No Roles assigned)
    Conference test_conference = new Conference(CONFERENCE_NAME, PAUL,
        pre_determined_users, TEST_DEADLINE);

    // Both William and Eric are now preloaded in the conference

    // Both William and Eric are not yet authors

    assertFalse(test_conference.hasSubmittedAPaper(WILLIAM));
    assertFalse(test_conference.hasSubmittedAPaper(ERIC));

    final Paper william_paper = new Paper("William's Paper", WILLIAM, IRVING,
        TEST_FILE);

    /* Note, you cannot submit a paper */
    /* containing an author that doesnt exist in conference */

    test_conference.assignReviewer(IRVING);
    test_conference.assignSubChair(IRVING);
    
    // william submits a paper to the conference
    test_conference.addPaper(william_paper);

    // William should now be considered an author

    assertTrue(test_conference.hasSubmittedAPaper(WILLIAM));
    assertFalse(test_conference.hasSubmittedAPaper(ERIC));

    // Eric submits a paper to the conference
    final Paper eric_paper = new Paper("Eric's Paper", ERIC, IRVING, TEST_FILE);
    test_conference.addPaper(eric_paper);

    // Both William and Eric should now be considered Authors

    assertTrue(test_conference.hasSubmittedAPaper(WILLIAM));
    assertTrue(test_conference.hasSubmittedAPaper(ERIC));

    List<Paper> expected = new ArrayList<Paper>();
    expected.add(william_paper);
    expected.add(eric_paper);

    assertEquals(expected, test_conference.getSubmittedPapers());

    // create 3 more papers by william

    // Test_file is the same for testing purposes
    final Paper william_paper2 = new Paper("William's Paper2", WILLIAM, IRVING,
        TEST_FILE);
    final Paper william_paper3 = new Paper("William's Paper3", WILLIAM, IRVING,
        TEST_FILE);
    final Paper william_paper4 = new Paper("William's Paper4", WILLIAM, IRVING,
        TEST_FILE);

    // submit 3 more papers by william

    test_conference.addPaper(william_paper2);
    test_conference.addPaper(william_paper3);
    test_conference.addPaper(william_paper4);

    // william should now have 4 papers in the conference
    // if an attempt to add 1 more paper, it should not be added

    final Paper extra = new Paper("William's extra paper", WILLIAM, PAUL,
        TEST_FILE);

    // submit the extra paper by william to the conference

    try
    {
      //attempt to add 1 more paper to the conference
      test_conference.addPaper(extra);
    } catch (final IllegalArgumentException e)
    {
      //should go to this statement
      assertTrue(true);
    }
    
    Date deadline = new Date();
    deadline.setYear(100); //sets year to 2000
    test_conference.setDeadline(deadline); //sets deadline of conference to 2000
    try {
      test_conference.addPaper(william_paper2);
    } catch(final IllegalArgumentException e) {
//      e.printStackTrace();
      assertTrue(true);
    }
  }

  @Test
  public void testAddUser()
  {
    // Create conference with no users
    Conference test_conference = new Conference(CONFERENCE_NAME, PAUL,
        TEST_DEADLINE);

    // Add 2 users with different usernames and email
    test_conference.addUser(WILLIAM);
    test_conference.addUser(ERIC);
    test_conference.addUser(PAUL);

    // Both users should have been added

    // users in conference at this point should be:
    // Paul, William, Eric
    // Size of users list should be 3
    int expected_size = 3;

    assertEquals(expected_size, test_conference.users().size());
    assertTrue(test_conference.users().contains(PAUL));
    assertTrue(test_conference.users().contains(WILLIAM));
    assertTrue(test_conference.users().contains(ERIC));

    // create user that is the same as William's username
    User invalid_user = new User("WilliamK", "invalid@yahoo.com");

    // invalid_user should not have been addded
    try
    {
      test_conference.addUser(invalid_user);
    } catch (final IllegalArgumentException e)
    {
      assertTrue(true);
    }
    // because another user had the same user name

    // still the same expected
    assertEquals(expected_size, test_conference.users().size());
    assertTrue(test_conference.users().contains(PAUL));
    assertTrue(test_conference.users().contains(WILLIAM));
    assertTrue(test_conference.users().contains(ERIC));

    // create user that is different username but same email
    invalid_user = new User("invalid_user", "W@fake.com");

    // invalid_user should not have been addded
    try
    {
      test_conference.addUser(invalid_user);
    } catch (final IllegalArgumentException e)
    {
      assertTrue(true);
    }
    // because another user had the same email

    // still the same expected
    assertTrue(test_conference.users().contains(PAUL));
    assertTrue(test_conference.users().contains(WILLIAM));
    assertTrue(test_conference.users().contains(ERIC));

    // create a valid user with different username and a different email
    User valid_user = new User("user_name", "email@yahoo.com");

    // add valid_user to conference
    test_conference.addUser(valid_user);

    // valid_user should have been added to conference
    // update expected
    expected_size = 4;
    assertEquals(expected_size, test_conference.users().size());
    assertTrue(test_conference.users().contains(PAUL));
    assertTrue(test_conference.users().contains(WILLIAM));
    assertTrue(test_conference.users().contains(ERIC));
    assertTrue(test_conference.users().contains(valid_user));

    // assertEquals(expected, test_conference.getUsers());
    // assertArrayEquals("valid user test2", expected.toArray(),
    // test_conference.getUsers().toArray());
  }

  @Test
  public void testGetPapersByAuthors()
  {
    // creates 2 papers with the same author
    final Paper paper1 = new Paper("Paper Title", WILLIAM, IRVING, TEST_FILE);
    final Paper paper2 = new Paper("Paper Title2", WILLIAM, IRVING, TEST_FILE2);
    final Paper paper3 = new Paper("Different Paper", IRVING, PAUL, TEST_FILE);

    // create conference
    Conference test_conference = new Conference(CONFERENCE_NAME, PAUL,
        TEST_DEADLINE);

    test_conference.addUser(WILLIAM);
    test_conference.addUser(IRVING);
    test_conference.addUser(NATHAN);

    test_conference.assignReviewer(IRVING);
    test_conference.assignSubChair(IRVING);
    test_conference.assignReviewer(NATHAN);

    test_conference.addPaper(paper1);
    assertTrue(test_conference.getPapersByAuthor(WILLIAM).size() == 1);
    assertTrue(test_conference.getPapersByAuthor(WILLIAM).contains(paper1));
  }

  @Test
  public void testGetPapersAssignedToSubChairs()
  {
    // create paper for william
    final Paper william_paper = new Paper("William Paper", WILLIAM, TEST_FILE);
    // create paper for nathan
    final Paper nathan_paper = new Paper("Nathan Paper", NATHAN, TEST_FILE2);

    // both papers have not yet been assigned a subprogram chair

    // create conference
    Conference test_conference = new Conference(CONFERENCE_NAME, PAUL,
        TEST_DEADLINE);

    // add users william and nathan
    test_conference.addUser(WILLIAM);
    test_conference.addUser(NATHAN);

    // both users are now registered but not yet authors

    // both william and nathan submits a paper
    test_conference.addPaper(william_paper);
    test_conference.addPaper(nathan_paper);
    // and are now authors

    // add irving to the conference
    test_conference.addUser(IRVING);

    // assign irving as a reviewer
    test_conference.assignReviewer(IRVING);

    // irving is now a reviewer
    test_conference.assignSubChair(IRVING);
    // and should be elligible to be a subprogram chair

    // Roles so far,
    // William and Nathan --> Author
    // Irving --> Reviewer, Subprogram Chair

    // Assign irving nathan's paper
    test_conference.assignPaperToSubChair(nathan_paper, IRVING);

    // create expected output
    List<Paper> expected = new ArrayList<Paper>();
    expected.add(nathan_paper);

    assertArrayEquals(expected.toArray(), test_conference
        .getPapersAssignedToSubChairs(IRVING).toArray());

    // attempt to assign a paper to a NON-sub chair
    try
    {
      test_conference.assignPaperToSubChair(william_paper, ERIC);
    } catch (final IllegalArgumentException e)
    {
      assertTrue(true);
    }

    // assigning a duplicate paper to the sub program chair
    try
    {
      test_conference.assignPaperToSubChair(nathan_paper, IRVING);
    } catch (final IllegalArgumentException e)
    {
      assertTrue(true);
    }

    // not yet tested
    // attempt to assign multiple papers to a sub chair under the limit

  }

  /**
   * @author Paul Schultz
   * */
  @Test
  public void testGetPapersByReviewers()
  {
    // Create three paper objects for testing
    final Paper paper1 = new Paper("Paper Title", WILLIAM, IRVING, TEST_FILE);
    final Paper paper2 = new Paper("Paper Title2", WILLIAM, IRVING, TEST_FILE2);
    final Paper paper3 = new Paper("Different Paper", IRVING, PAUL, TEST_FILE);

    // Assign 2 papers to first Reviewer
    paper1.editReview(NATHAN, TEST_FILE);
    paper2.editReview(NATHAN, TEST_FILE);

    // Assign other paper to second Reviewer
    paper3.editReview(WILLIAM, TEST_FILE2);

    // Create new Conference
    Conference test_conference = new Conference(CONFERENCE_NAME, PAUL,
        TEST_DEADLINE);

    test_conference.addUser(WILLIAM);
    test_conference.addUser(NATHAN);
    test_conference.addUser(IRVING);
    test_conference.addUser(PAUL);

    test_conference.assignReviewer(IRVING);
    test_conference.assignSubChair(IRVING);
    
    test_conference.assignReviewer(PAUL);
    test_conference.assignSubChair(PAUL);

    // Submit the Papers
    test_conference.addPaper(paper1);
    test_conference.addPaper(paper2);
    test_conference.addPaper(paper3);

    // Expected Return Value (Only papers assigned to Nathan for review)
    List<Paper> expected = new ArrayList<Paper>();
    expected.add(paper1);
    expected.add(paper2);

    assertArrayEquals("getPapersByAuthors", expected.toArray(), test_conference
        .getPapersAssignedToReviewers(NATHAN).toArray());

    // Attempt to get papers by an invalid Reviewer.
    // An exception should be thrown in this case.
    try
    {
      test_conference.getPapersAssignedToReviewers(ERIC);
    } catch (IllegalArgumentException e)
    {
      // Asserts that an exception is thrown.
      assertTrue(true);
    }

  }

  @Test
  public void testUnsubmitPaper()
  {
    // create 2 papers with the same author
    final Paper paper1 = new Paper("Paper Title", WILLIAM, IRVING, TEST_FILE);
    final Paper paper2 = new Paper("Paper Title2", WILLIAM, IRVING, TEST_FILE);

    // create 1 paper with a different author
    final Paper paper3 = new Paper("Paper Title3", ERIC, IRVING, TEST_FILE);

    // create conference
    Conference test_conference = new Conference(CONFERENCE_NAME, PAUL,
        TEST_DEADLINE);
    test_conference.addUser(WILLIAM);
    test_conference.addUser(ERIC);
    test_conference.addUser(IRVING);

    test_conference.assignReviewer(IRVING);
    test_conference.assignSubChair(IRVING);
    
    // submit papers
    test_conference.addPaper(paper1);
    test_conference.addPaper(paper2);
    test_conference.addPaper(paper3);

    // remove paper2
    test_conference.removePaper(paper2);

    // papers in the conference should now only be paper1 and paper3

    List<Paper> expected = new ArrayList<Paper>();
    expected.add(paper1);
    expected.add(paper3);

    List<Paper> actual = test_conference.getSubmittedPapers();

    assertArrayEquals("testUnsubmit", expected.toArray(), actual.toArray());
  }

  @Test
  public void testAssignReviewer()
  {
    // create a coference
    Conference test_conference = new Conference(CONFERENCE_NAME, PAUL,
        TEST_DEADLINE);
    // add users
    test_conference.addUser(WILLIAM);
    test_conference.addUser(IRVING);
    test_conference.addUser(NATHAN);
    
    test_conference.assignReviewer(IRVING);
    test_conference.assignSubChair(IRVING);

    // create papers
    Paper nathan_paper = new Paper("Nathan's Paper", NATHAN, IRVING, TEST_FILE);

    // submit papers
    test_conference.addPaper(nathan_paper);

    // after submitting, nathan is now an author

    // assign nathan as reviewer
    test_conference.assignReviewer(NATHAN);

    // Nathan should now be an author and a reviewer
    List<Role> expected_roles = new ArrayList<Role>();
    expected_roles.add(Role.AUTHOR);
    expected_roles.add(Role.REVIEWER);

    List<Role> actual = test_conference.userMappings().get(NATHAN);
    assertArrayEquals("assignReviewer", expected_roles.toArray(),
        actual.toArray());
  }

  @Test
  public void testAssignSubChair()
  {
    // create a coference
    Conference test_conference = new Conference(CONFERENCE_NAME, PAUL,
        TEST_DEADLINE);
    // add users
    test_conference.addUser(WILLIAM);
    test_conference.addUser(IRVING);
    test_conference.addUser(NATHAN);
    test_conference.addUser(PAUL);
    
    test_conference.assignReviewer(IRVING);
    test_conference.assignSubChair(IRVING);
    test_conference.assignReviewer(PAUL);
    test_conference.assignSubChair(PAUL);

    // create papers
    Paper william_paper = new Paper("William's Paper", WILLIAM, IRVING, TEST_FILE);
    Paper irving_paper = new Paper("Irving's Paper", IRVING, PAUL, TEST_FILE);

    // submit papers
    test_conference.addPaper(william_paper);
    test_conference.addPaper(irving_paper);

    // assign nathan as reviewer
    test_conference.assignReviewer(NATHAN);

    // Nathan should now be given the reviewer role
    // and can be assigned as a sub program chair

    test_conference.assignSubChair(NATHAN);

    // Nathan should now have been given the sub chair role
    // Nathan is now both a reviewer and a sub chair

    List<Role> expected_roles = new ArrayList<Role>();
    expected_roles.add(Role.REVIEWER);
    expected_roles.add(Role.SUB_CHAIR);

    List<Role> actual = test_conference.userMappings().get(NATHAN);
    assertArrayEquals("assignSubChair", expected_roles.toArray(),
        actual.toArray());
  }

  @Test
  public void testAssignPaperToReviewers()
  {
    // create a coference
    Conference test_conference = new Conference(CONFERENCE_NAME, PAUL,
        TEST_DEADLINE);
    // add users
    test_conference.addUser(WILLIAM);
    test_conference.addUser(IRVING);
    test_conference.addUser(NATHAN);

    // create william's paper
    Paper william_paper = new Paper("William's Paper", WILLIAM, TEST_FILE);
    Paper william_paper2 = new Paper("William's Paper2", WILLIAM, TEST_FILE);

    // assign nathan and irving a reviewer
    test_conference.assignReviewer(IRVING);
    test_conference.assignReviewer(NATHAN);

    // william submits both papers
    test_conference.addPaper(william_paper);
    test_conference.addPaper(william_paper2);

    // irving gets assigned as a subchair
    test_conference.assignSubChair(IRVING);

    // assigned a paper to irving
    test_conference.assignPaperToSubChair(william_paper, IRVING);
    test_conference.assignPaperToReviewers(william_paper, NATHAN);

    assertTrue(test_conference.getPapersAssignedToReviewers(IRVING).size() == 0);
    assertTrue(test_conference.getPapersAssignedToSubChairs(IRVING).size() == 1);
    assertTrue(test_conference.getPapersAssignedToReviewers(NATHAN).size() == 1);
    assertTrue(test_conference.getPapersAssignedToSubChairs(IRVING).contains(
        william_paper));
    assertTrue(test_conference.getPapersAssignedToReviewers(NATHAN).contains(
        william_paper));
  }
}
